﻿using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using RabbitMQ.Client;

namespace Rmq.Center
{
    public class BaseProducer<T>
    {
        private readonly string _routingKey;

        public BaseProducer(string routingKey)
        {
            _routingKey = routingKey;
        }

        public virtual void Publish(T msg, int delayInMs = 0)
        {
            var wrappedMsg = new Msg<T>(msg);
            Publish(wrappedMsg, delayInMs);
        }

        private void Publish(Msg<T> wrappedMsg, int delayInMs)
        {
            var factory = new ConnectionFactory()
            {
                HostName = Const.HostName,
                UserName = Const.UserName,
                Password = Const.Password,
            };
            factory.AutomaticRecoveryEnabled = true;
            factory.TopologyRecoveryEnabled = true;
            using (var connection = factory.CreateConnection())
            using (var channel = connection.CreateModel())
            {
                // declare normal exchange
                channel.ExchangeDeclare(
                    exchange: Const.ExchangeName,
                    type: "topic",
                    durable: true,
                    autoDelete: false,
                    arguments: null);

                // declare delayed exchange
                var exchangeArguments = new Dictionary<string, object>();
                exchangeArguments.Add("x-delayed-type", "topic");
                channel.ExchangeDeclare(
                    exchange: Const.DelayedExchangeName,
                    type: "x-delayed-message",
                    durable: true,
                    autoDelete: false,
                    arguments: exchangeArguments);

                var body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(wrappedMsg));

                if (delayInMs > 0)
                {
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;
                    properties.Headers = new Dictionary<string, object>();
                    properties.Headers.Add("x-delay", delayInMs);

                    channel.BasicPublish(exchange: Const.DelayedExchangeName,
                        routingKey: _routingKey,
                        basicProperties: properties,
                        body: body);
                }
                else
                {
                    var properties = channel.CreateBasicProperties();
                    properties.Persistent = true;

                    channel.BasicPublish(exchange: Const.ExchangeName,
                        routingKey: _routingKey,
                        basicProperties: properties,
                        body: body);
                }

            }
        }
    }
}